#include "algorithm.h"

Algorithm::Algorithm()
{

}

  QList<double> Algorithm::GetNumList(int num)
{
    QList<double> list;
    for(int i=1;i<=num;i++)
    {
        list.append(i);
    }
    return list;
}

  QList<double> Algorithm::GetNumList(int num,double startData,double d)
{
    QList<double> list;
    double sumD=startData;
    list.append(sumD);
    for(int i=1;i<num;i++)
    {
        sumD+=d;
        list.append(sumD);
    }
    return list;
}

//均值滤波//filter
 QList<double> Algorithm::FilterMean(QList<double> datas)
{
    QList<double> list;
    int d=5;//
    int count=datas.count();
    if(count<d) return datas;

    double data;
    data=datas.at(0);
    list.append(data);
    data=(datas.at(0)+datas.at(1))/2;
    list.append(data);
    for(int i=2;i<count-2;i++)
    {
        data=(datas.at(i-2)+datas.at(i-1)+datas.at(i)+datas.at(i+1)+datas.at(i+2))/5;
        list.append(data);
    }
    data=(datas.at(count-3)+datas.at(count-2)+datas.at(count-1))/3;
    list.append(data);
    data=datas.at(count-1);
    list.append(data);
    /*
    for(;i<count;i++)
    {
        data=datas.at(i);
        list.append(data);
    }
    */
    return list;
}

//
 double Algorithm::MeanData(QList<double> datas)
{
    int count=datas.count();
    if(count==0) return 0;

    double sum=0;
    foreach(double data,datas)
    {
        sum+=data;
    }
    return sum/count;
}

 double Algorithm::SdData(QList<double> datas)
{
    int count=datas.count();
    if(count==0) return 0;

    double mean=MeanData(datas);
    double sum=0;
    foreach(double data,datas)
    {
        sum+=(data-mean)*(data-mean);
    }
    return sqrt(sum/(count-1));
}
 double Algorithm::RsdData(QList<double> datas)
 {
     int count=datas.count();
     if(count==0) return 0;
     double mean=MeanData(datas);
     if(mean==0) return 0;

     double sum=0;
     foreach(double data,datas)
     {
         sum+=(data-mean)*(data-mean);
     }
     return sqrt(sum/((count-1)*fabs(mean)));//abs
 }

 //random
 void Algorithm::InitRand()
 {
     qsrand(QTime(0,0,0).secsTo(QTime::currentTime())+ qrand());
 }

 double Algorithm::Rand(double min,double max)
 {
     int value=min+qrand()/(double)(RAND_MAX/(max-min));
     return value;
 }

 //先处理 再序列参数
 QList<ScanPara> Algorithm::GetHopScanPara(QHash<QString,HopScanPara> paras0)//paras
 {
     //
     QMap<double,HopScanPara> paras;
     foreach(HopScanPara para,paras0)
     {
         paras.insert(para.massNum,para);
     }

     QList<ScanPara> scanParas;
     foreach(HopScanPara para,paras.values())
     {
         //if(para.bIsUsed==false) continue;//
         ScanPara scanPara;
         scanPara.name=para.name;
         scanPara.startMassNum=para.massNum-(para.chanels/2)*para.interval;
         scanPara.endMassNum=para.massNum+(para.chanels/2)*para.interval;
         scanPara.channels=para.chanels;
         scanPara.type=para.type;
         scanPara.interval=para.interval;
         scanPara.bIsDisplay=para.bIsDisplay;
         scanPara.color=para.color;
         scanParas.append(scanPara);
     }
     return scanParas;
 }
 QList<ScanPara> Algorithm::GetSweepScanPara(QList<SweepScanPara> paras0)
 {
     QMap<double,SweepScanPara> paras;
     foreach(SweepScanPara para,paras0)
     {
         paras.insert(para.startMassNum,para);
     }

     QList<ScanPara> scanParas;
     foreach(SweepScanPara para,paras)
     {
         //if(para.bIsUsed==false) continue;//

         ScanPara scanPara;
         scanPara.name=para.name;
         scanPara.startMassNum=para.startMassNum;
         scanPara.endMassNum=para.endMassNum;
         scanPara.channels=(para.endMassNum-para.startMassNum)*para.channelsAmu;
         scanPara.type=para.type;
         scanPara.interval=(para.endMassNum-para.startMassNum)/(scanPara.channels-1);//
         scanPara.bIsDisplay=para.bIsDisplay;
         scanPara.color=para.color;
         scanParas.append(scanPara);
     }
     return scanParas;
 }
 QList<ScanPara> Algorithm::GetSweepScanPara(QHash<QString,SweepScanPara> paras0)
 {
     QMap<double,SweepScanPara> paras;
     foreach(SweepScanPara para,paras0)
     {
         paras.insert(para.startMassNum,para);
     }

     QList<ScanPara> scanParas;
     foreach(SweepScanPara para,paras)
     {
         //if(para.bIsUsed==false) continue;//
         ScanPara scanPara;
         scanPara.name=para.name;
         scanPara.startMassNum=para.startMassNum;
         scanPara.endMassNum=para.endMassNum;
         scanPara.channels=(para.endMassNum-para.startMassNum)*para.channelsAmu;
         scanPara.type=para.type;
         scanPara.interval=(para.endMassNum-para.startMassNum)/(scanPara.channels-1);//
         scanPara.bIsDisplay=para.bIsDisplay;
         scanPara.color=para.color;
         scanParas.append(scanPara);
     }
     return scanParas;
 }
//
 bool Algorithm::MergeSweepScanPara(QList<QPair<double,double> > pairs,QList<SweepScanPara> &paras,int index)
 {
     QList<SweepScanPara> paras0;
     QList<SweepScanPara> paras1;
     bool state=false;
     SweepScanPara currentPara=paras.at(index);
     for(int i=0;i<paras.count();i++)
     {
         if(i==index) continue;
         SweepScanPara scanPara=paras.at(i);
         if(scanPara.startMassNum>currentPara.endMassNum||scanPara.endMassNum<currentPara.startMassNum)
         {
            paras0.append(scanPara);
         }
         else //更新
         {
             state=true;
             if(scanPara.startMassNum<currentPara.startMassNum)
             {
                 currentPara.startMassNum=scanPara.startMassNum;
             }
             if(scanPara.endMassNum>currentPara.endMassNum)
             {
                 currentPara.endMassNum=scanPara.endMassNum;
             }
         }
     }
     paras0.append(currentPara);

     foreach(SweepScanPara para,paras0)
     {
         for(int i=0;i<pairs.count();i++)
         {
             QPair<double,double>  pair=pairs.at(i);
             if(pair.first>para.endMassNum||pair.second<para.startMassNum)
             {
             }
             else
             {
                 SweepScanPara temp=para;
                 if(temp.startMassNum<pair.first)
                 {
                     state=true;
                     temp.startMassNum=pair.first;
                 }
                 if(temp.endMassNum>pair.second)
                 {
                     state=true;
                     temp.endMassNum=pair.second;
                 }
                 paras1.append(temp);
             }
         }
     }
     qDebug()<<"state"<<state<<"index"<<index;
     qDebug()<<"pairs"<<pairs.count();
     for(int i=0;i<pairs.count();i++)
     {
         QPair<double,double>  pair=pairs.at(i);
         qDebug()<<"pair"<<pair.first<<pair.second;
     }
     qDebug()<<"paras0"<<paras0.count();
     foreach(SweepScanPara para,paras0)
     {
         qDebug()<<"paras0 MassNum"<<para.startMassNum<<para.endMassNum;
     }
     qDebug()<<"paras1"<<paras1.count();
     foreach(SweepScanPara para,paras1)
     {
         qDebug()<<"paras1 MassNum"<<para.startMassNum<<para.endMassNum;
     }
     paras=paras1;

     return state;
 }

 bool Algorithm::Max(QList<double> xs,double &max,int &index)
 {
     if(xs.count()<1) return false;

     max=xs.at(0);
     for(int i=0;i<xs.count();i++)
     {
         double value=xs.at(i);
         if(value>max)
         {
             max=value;
             index=i;
         }
     }

     return true;
 }
 double Algorithm::CalResolution(QList<double> xs,QList<double> ys)
 {
     if(xs.count()<10) return 0;
     if(xs.last()-xs.first()<1) return 0;
     if(ys.count()<10) return 0;//

     double x1,x2;
     double max,temp;
     int index,leftIndex2=0,leftIndex1=0,rightIndex1=ys.count(),rightIndex2=ys.count();
     Max(ys,max,index);
     temp=0.1*max;
     for(int i=index-1;i>=0;i--)//
     {
        if(ys.at(i)<temp)
        {
            leftIndex1=i+1;
            leftIndex2=i;
            break;
        }
        else if(ys.at(i)==temp)
        {
            leftIndex1=i;
            leftIndex2=i;
            break;
        }
     }
     if(leftIndex1==leftIndex2)
     {
         x1=xs.at(leftIndex1);
     }
     else
     {
         x1=(temp-ys.at(leftIndex2))*(xs.at(leftIndex1)-xs.at(leftIndex2))/(ys.at(leftIndex1)-ys.at(leftIndex2))+xs.at(leftIndex2);
     }

     for(int i=index+1;i<ys.count()-1;i++)//
     {
         if(ys.at(i)<temp)
         {
             rightIndex1=i-1;
             rightIndex2=i;
             break;
         }
         else if(ys.at(i)==temp)
         {
             rightIndex1=i;
             rightIndex2=i;
             break;
         }
     }
     if(rightIndex1==rightIndex2)
     {
         x2=xs.at(rightIndex1);
     }
     else
     {
         x2=(temp-ys.at(rightIndex2))*(xs.at(rightIndex1)-xs.at(rightIndex2))/(ys.at(rightIndex1)-ys.at(rightIndex2))+xs.at(rightIndex2);
     }

     return (x2-x1);
 }


 QList<SweepScanPara> Algorithm::CalSweepPara(QList<QPair<double,double> > forbidRangs,QList<SweepScanPara> setRangs)
 {
     QList<SweepScanPara> tempRangs;
     int count;
     double startMass1,endMass1,startMass2,endMass2;
     count=setRangs.count();
     if(count>=2)
     {
         startMass1=setRangs.at(0).startMassNum;
         endMass1=setRangs.at(0).endMassNum;
         for(int i=1;i<count;i++)
         {
             startMass2=setRangs.at(i).startMassNum;
             endMass2=setRangs.at(i).endMassNum;
         }
     }
     return tempRangs;
 }

 /*==================polyfit(n,x,y,poly_n,a)===================*/
 /*=======拟合y=a0+a1*x+a2*x^2+……+apoly_n*x^poly_n========*/
 /*=====n是数据个数 xy是数据值 poly_n是多项式的项数======*/
 /*===返回a0,a1,a2,……a[poly_n]，系数比项数多一（常数项）=====*/
 void Algorithm::PolyFit(QList<double> w,QList<double> x,QList<double> y,QList<double> &p)
 {
     int i,j,n,poly_n;
     QList<double> tempw;
     QList<double> tempx;
     QList<double> tempy;
     QList<double> sumxx;
     QList<double> sumxy;
     QList<double> ata;

     n=x.count(),
     poly_n=p.count()-1;
     for(int i=0;i<n;i++)
     {
         tempw.append(0);
     }
     for(int i=0;i<n;i++)
     {
         tempx.append(0);
     }
     for(int i=0;i<n;i++)
     {
         tempy.append(0);
     }
     for(int i=0;i<(poly_n*2+1);i++)
     {
         sumxx.append(0);
     }
     for(int i=0;i<(poly_n+1);i++)
     {
         sumxy.append(0);
     }
     for(int i=0;i<(poly_n+1)*(poly_n+1);i++)
     {
         ata.append(0);
     }

     for (i=0;i<n;i++)
     {
         tempx[i]=1;
         tempy[i]=y[i];
         tempw[i]=w[i];
     }
     for (i=0;i<2*poly_n+1;i++)
     {
         for (sumxx[i]=0,j=0;j<n;j++)
         {
             sumxx[i]+=tempx[j]*w[j];//
             tempx[j]*=x[j];
         }
     }
     for (i=0;i<poly_n+1;i++)
     {
         for (sumxy[i]=0,j=0;j<n;j++)
         {
             sumxy[i]+=tempy[j]*w[j];//
             tempy[j]*=x[j];
         }
     }
     for (i=0;i<poly_n+1;i++)
     {
         for (j=0;j<poly_n+1;j++)
         {
             ata[i*(poly_n+1)+j]=sumxx[i+j];
         }
     }
     GaussSolve(ata,p,sumxy);
 }
 /*============================================================*/
 ////	高斯消元法计算得到	n 次多项式的系数
 ////	n: 系数的个数
 ////	ata: 线性矩阵
 ////	sumxy: 线性方程组的Y值
 ////	p: 返回拟合的结果
 /*============================================================*/
 void Algorithm::GaussSolve(QList<double> A,QList<double> &x,QList<double> b)
 {
     int i,j,k,r,n;
     double max;
     n=b.count();
     for (k=0;k<n-1;k++)
     {
         max=fabs(A[k*n+k]);					// find maxmum
         r=k;
         for (i=k+1;i<n-1;i++)
         {
             if (max<fabs(A[i*n+i]))
             {
                 max=fabs(A[i*n+i]);
                 r=i;
             }
         }
         if (r!=k)
         {
             for (i=0;i<n;i++)		//change array:A[k]&A[r]
             {
                 max=A[k*n+i];
                 A[k*n+i]=A[r*n+i];
                 A[r*n+i]=max;
             }
             max=b[k];                    //change array:b[k]&b[r]
             b[k]=b[r];
             b[r]=max;
         }

         for (i=k+1;i<n;i++)
         {
             for (j=k+1;j<n;j++)
                 A[i*n+j]-=A[i*n+k]*A[k*n+j]/A[k*n+k];
             b[i]-=A[i*n+k]*b[k]/A[k*n+k];
         }
     }

     for (i=n-1;i>=0;x[i]/=A[i*n+i],i--)
     {
         for (j=i+1,x[i]=b[i];j<n;j++)
             x[i]-=A[i*n+j]*x[j];
     }
 }

 QList<double> Algorithm::ratios;
 void Algorithm::SetRatios(QList<double> datas)
 {
     ratios=datas;
 }
 double Algorithm::Func(double x)
 {
     double y=0;
     int count=ratios.count();
     for(int i=0;i<count;i++)
     {
        switch(i)
        {
        case 0:
            y+=ratios.at(0);
            break;
        case 1:
            y+=ratios.at(1)*x;
            break;
        case 2:
            y+=ratios.at(2)*x*x;
            break;
        case 3:
            y+=ratios.at(3)*x*x*x;
            break;
        case 4:
            y+=ratios.at(4)*x*x*x*x;
            break;
        }
     }
     return y;
 }

